bitkeeper revision 1.1023.1.6 (40e15b7edePZdBO_2yFHsmAtSxfw9g)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Tue, 29 Jun 2004 12:07:26 +0000 (12:07 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Tue, 29 Jun 2004 12:07:26 +0000 (12:07 +0000)
Change to using the vifctl script to init networking and
bring vifs up and down instead of doing it all ourselves.

.rootkeys
tools/xen/Makefile
tools/xen/lib/util/Brctl.py [new file with mode: 0644]
tools/xen/lib/xend/Vifctl.py [new file with mode: 0644]
tools/xen/lib/xend/XendBridge.py [deleted file]
tools/xen/lib/xend/XendDomainInfo.py
tools/xen/lib/xend/server/SrvServer.py
tools/xen/lib/xend/server/netif.py
tools/xen/vifctl [new file with mode: 0644]

index c2f8c5d26e9b44d2bb0d9317f4065336d84b209c..91a12ae1e3b7fe547903a018eb49434354fe5a8b 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
 40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
 40dfd40aMOhnw_cQLve9462UR5yYxQ tools/xen/lib/ext/__init__.py
+40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xen/lib/util/Brctl.py
 40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/xen/lib/util/__init__.py
 4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xen/lib/util/console_client.py
 40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xen/lib/util/ip.py
 40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
 40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
 40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xen/lib/xend/PrettyPrint.py
-40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xen/lib/xend/XendBridge.py
+40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/xen/lib/xend/Vifctl.py
 40c9c4688m3eqnC8fhLu1APm36VOVA tools/xen/lib/xend/XendClient.py
 40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xen/lib/xend/XendConsole.py
 40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xen/lib/xend/XendDB.py
 40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xen/lib/xm/shutdown.py
 40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xen/netfix
 40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
+40e15b7edWEtBf_oe3eBwGKuh1dyzQ tools/xen/vifctl
 40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
 40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
 40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend-old/Makefile
index 642cd2273e238202e0be51f3d9e40647c72dec89..8732a309329de21bf4e2b4180de1b2dc392ccd28 100644 (file)
@@ -14,6 +14,8 @@ install: all
        install -m0755 xend $(prefix)/usr/sbin
        install -m0755 netfix $(prefix)/usr/sbin
        install -m0755 xm $(prefix)/usr/sbin
+       mkdir -p $(prefix)/etc/xen/xend
+       install -m0755 vifctl $(prefix)/etc/xen/xend
 
 clean:
        rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/xen/lib/util/Brctl.py b/tools/xen/lib/util/Brctl.py
new file mode 100644 (file)
index 0000000..32dd16b
--- /dev/null
@@ -0,0 +1,161 @@
+"""Bridge control utilities.
+"""
+import os
+import os.path
+import re
+import sys
+
+os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
+CMD_IFCONFIG = 'ifconfig'
+CMD_ROUTE    = 'route'
+CMD_BRCTL    = 'brctl'
+CMD_IPTABLES = "iptables"
+
+opts = None
+
+class Opts:
+
+    def __init__(self, defaults):
+        for (k, v) in defaults.items():
+            setattr(self, k, v)
+        pass
+
+def cmd(p, s):
+    """Print and execute command 'p' with args 's'.
+    """
+    global opts
+    c = p + ' ' + s
+    if opts.verbose: print c
+    if not opts.dryrun:
+        os.system(c)
+
+def vif_bridge_add(params):
+    """Add the network interface for vif on dom to a bridge.
+    """
+    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % params)
+    return bridge
+
+def vif_bridge_rem(params):
+    """Remove the network interface for vif on dom from a bridge.
+    """
+    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % params)
+
+def vif_restrict_addr(vif, addr, delete=0):
+    d = { 'vif': vif, 'addr': addr}
+    if delete:
+        d['flag'] = '-D'
+    else:
+        d['flag'] = '-A'
+    cmd(CMD_IPTABLES, '-P FORWARD DROP')
+    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
+    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
+
+def bridge_create(bridge, **kwd):
+    """Create a bridge.
+    Defaults hello time to 0, forward delay to 0 and stp off.
+    """
+    cmd(CMD_BRCTL, 'addbr %s' % bridge)
+    if kwd.get('hello', None) is None:
+        kwd['hello'] = 0
+    if kwd.get('fd', None) is None:
+        kwd['fd'] = 0
+    if kwd.get('stp', None) is None:
+        kwd['stp'] = 'off'
+    bridge_set(bridge, **kwd)
+
+def bridge_set(bridge, hello=None, fd=None, stp=None):
+    """Set bridge parameters.
+    """
+    if hello is not None:
+        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
+    if fd is not None:
+        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
+    if stp is not None:
+        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
+
+def bridge_del(bridge):
+    """Delete a bridge.
+    """
+    cmd(CMD_BRCTL, 'delbr %s' % bridge)
+
+def routes():
+    """Return a list of the routes.
+    """
+    fin = os.popen(CMD_ROUTE + ' -n', 'r')
+    routes = []
+    for x in fin:
+        if x.startswith('Kernel'): continue
+        if x.startswith('Destination'): continue
+        x = x.strip()
+        y = x.split()
+        z = { 'destination': y[0],
+              'gateway'    : y[1],
+              'mask'       : y[2],
+              'flags'      : y[3],
+              'metric'     : y[4],
+              'ref'        : y[5],
+              'use'        : y[6],
+              'interface'  : y[7] }
+        routes.append(z)
+    return routes
+
+def ifconfig(interface):
+    """Return the ip config for an interface,
+    """
+    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
+    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
+    info = None
+    for x in fin:
+        m = inetre.match(x)
+        if not m: continue
+        info = m.groupdict()
+        info['interface'] = interface
+        break
+    return info
+
+def reconfigure(interface, bridge):
+    """Reconfigure an interface to be attached to a bridge, and give the bridge
+    the IP address etc. from interface. Move the default route to the interface
+    to the bridge.
+
+    """
+    global opts
+    intf_info = ifconfig(interface)
+    if not intf_info:
+        print 'Interface not found:', interface
+        return
+    #bridge_info = ifconfig(bridge)
+    #if not bridge_info:
+    #    print 'Bridge not found:', bridge
+    #    return
+    route_info = routes()
+    intf_info['bridge'] = bridge
+    intf_info['gateway'] = None
+    for r in route_info:
+        if (r['destination'] == '0.0.0.0' and
+            'G' in r['flags'] and
+            r['interface'] == interface):
+            intf_info['gateway'] = r['gateway']
+    if not intf_info['gateway']:
+        print 'Gateway not found: ', interface
+        return
+    cmd(CMD_IFCONFIG,
+        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
+        % intf_info)
+    cmd(CMD_ROUTE,
+        'add default gateway %(gateway)s dev %(bridge)s'
+        % intf_info)
+    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
+    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
+
+defaults = {
+    'verbose'  : 1,
+    'dryrun'   : 0,
+    }
+
+opts = Opts(defaults)
+
+def set_opts(val):
+    global opts
+    opts = val
+    return opts
diff --git a/tools/xen/lib/xend/Vifctl.py b/tools/xen/lib/xend/Vifctl.py
new file mode 100644 (file)
index 0000000..49df8f6
--- /dev/null
@@ -0,0 +1,28 @@
+import os
+import os.path
+import sys
+
+VIFCTL = '/etc/xen/xend/vifctl'
+
+def init():
+    os.system(VIFCTL + ' init ')
+
+def up(vif, mac=None, bridge=None, ipaddr=[]):
+    args = ['vif=%s' % vif]
+    if mac:
+        args.append('mac=%s' % mac)
+    if bridge:
+        args.append('bridge=%s' % bridge)
+    if ipaddr:
+        args.append('ipaddr=%s' % ','.join(ipaddr))
+    os.system(VIFCTL + ' up ' + ' '.join(args))
+
+def down(vif, mac=None, bridge=None, ipaddr=[]):
+    args = ['vif=%s' % vif]
+    if mac:
+        args.append('mac=%s' % mac)
+    if bridge:
+        args.append('bridge=%s' % bridge)
+    if ipaddr:
+        args.append('ipaddr=%s' % ','.join(ipaddr))
+    os.system(VIFCTL + ' down ' + ' '.join(args))
diff --git a/tools/xen/lib/xend/XendBridge.py b/tools/xen/lib/xend/XendBridge.py
deleted file mode 100644 (file)
index f158455..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-"""Bridge control utilities.
-"""
-import os
-import os.path
-import re
-import sys
-
-from xen.xend import XendRoot
-xroot = XendRoot.instance()
-
-os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
-CMD_IFCONFIG = 'ifconfig'
-CMD_ROUTE    = 'route'
-CMD_BRCTL    = 'brctl'
-CMD_IPTABLES = "iptables"
-
-DEFAULT_BRIDGE = 'nbe-br'
-DEFAULT_INTERFACE = 'eth0'
-
-opts = None
-
-class Opts:
-
-    def __init__(self, defaults):
-        for (k, v) in defaults.items():
-            setattr(self, k, v)
-        pass
-
-def cmd(p, s):
-    """Print and execute command 'p' with args 's'.
-    """
-    global opts
-    c = p + ' ' + s
-    if opts.verbose: print c
-    if not opts.dryrun:
-        os.system(c)
-
-def default_bridge():
-    return xroot.get_config_value('bridge', DEFAULT_BRIDGE)
-
-def default_interface():
-    return xroot.get_config_value('interface', DEFAULT_INTERFACE)
-
-def vif_dev(dom, vif):
-    """Return the name of the network interface for vif on domain dom.
-    """
-    return "vif%d.%d" % (dom, vif)
-
-def vif_bridge_add(dom, vif, bridge=None):
-    """Add the network interface for vif on dom to a bridge.
-    """
-    if not bridge: bridge = default_bridge()
-    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
-    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % d)
-    return bridge
-
-def vif_bridge_rem(dom, vif, bridge=None):
-    """Remove the network interface for vif on dom from a bridge.
-    """
-    if not bridge: bridge = default_bridge()
-    print 'vif_bridge_rem>', dom, vif, bridge
-    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
-    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % d)
-
-def vif_restrict_addr(dom, vif, addr, delete=0):
-    d = { 'vif': vif_dev(dom, vif), 'addr': addr}
-    if delete:
-        d['flag'] = '-D'
-    else:
-        d['flag'] = '-A'
-    cmd(CMD_IPTABLES, '-P FORWARD DROP')
-    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
-    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
-
-def bridge_create(bridge=None, **kwd):
-    """Create a bridge.
-    Defaults hello time to 0, forward delay to 0 and stp off.
-    """
-    if not bridge: bridge = default_bridge()
-    cmd(CMD_BRCTL, 'addbr %s' % bridge)
-    if kwd.get('hello', None) is None:
-        kwd['hello'] = 0
-    if kwd.get('fd', None) is None:
-        kwd['fd'] = 0
-    if kwd.get('stp', None) is None:
-        kwd['stp'] = 'off'
-    bridge_set(bridge, **kwd)
-
-def bridge_set(bridge, hello=None, fd=None, stp=None):
-    """Set bridge parameters.
-    """
-    if hello is not None:
-        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
-    if fd is not None:
-        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
-    if stp is not None:
-        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
-
-def bridge_del(bridge=None):
-    """Delete a bridge.
-    """
-    if not bridge: bridge = default_bridge()
-    cmd(CMD_BRCTL, 'delbr %s' % bridge)
-
-def routes():
-    """Return a list of the routes.
-    """
-    fin = os.popen(CMD_ROUTE + ' -n', 'r')
-    routes = []
-    for x in fin:
-        if x.startswith('Kernel'): continue
-        if x.startswith('Destination'): continue
-        x = x.strip()
-        y = x.split()
-        z = { 'destination': y[0],
-              'gateway'    : y[1],
-              'mask'       : y[2],
-              'flags'      : y[3],
-              'metric'     : y[4],
-              'ref'        : y[5],
-              'use'        : y[6],
-              'interface'  : y[7] }
-        routes.append(z)
-    return routes
-
-def ifconfig(interface):
-    """Return the ip config for an interface,
-    """
-    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
-    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
-    info = None
-    for x in fin:
-        m = inetre.match(x)
-        if not m: continue
-        info = m.groupdict()
-        info['interface'] = interface
-        break
-    return info
-
-def reconfigure(interface=None, bridge=None):
-    """Reconfigure an interface to be attached to a bridge, and give the bridge
-    the IP address etc. from interface. Move the default route to the interface
-    to the bridge.
-
-    If opts.create is true, creates the bridge.
-    """
-    global opts
-    if not interface: interface = default_interface()
-    if not bridge: bridge = default_bridge()
-    intf_info = ifconfig(interface)
-    if not intf_info:
-        print 'Interface not found:', interface
-        return
-    if opts.create:
-        bridge_create(bridge)
-    #bridge_info = ifconfig(bridge)
-    #if not bridge_info:
-    #    print 'Bridge not found:', bridge
-    #    return
-    route_info = routes()
-    intf_info['bridge'] = bridge
-    intf_info['gateway'] = None
-    for r in route_info:
-        if (r['destination'] == '0.0.0.0' and
-            'G' in r['flags'] and
-            r['interface'] == interface):
-            intf_info['gateway'] = r['gateway']
-    if not intf_info['gateway']:
-        print 'Gateway not found: ', interface
-        return
-    cmd(CMD_IFCONFIG,
-        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
-        % intf_info)
-    cmd(CMD_ROUTE,
-        'add default gateway %(gateway)s dev %(bridge)s'
-        % intf_info)
-    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
-    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
-
-defaults = {
-    'interface': default_interface(),
-    'bridge'   : default_bridge(),
-    'verbose'  : 1,
-    'dryrun'   : 0,
-    'create'   : 0,
-    }
-
-opts = Opts(defaults)
-
-def set_opts(val):
-    global opts
-    opts = val
-    return opts
index c17109c85aaeab815213d403b9ac9813c718be0b..50fcf26fe2517ae8eb086a1bf78f4c6fc158a1e6 100644 (file)
@@ -24,8 +24,6 @@ import sxp
 import XendConsole
 xendConsole = XendConsole.instance()
 
-import XendBridge
-
 import server.SrvDaemon
 xend = server.SrvDaemon.instance()
 
@@ -765,7 +763,7 @@ def vm_dev_vif(vm, val, index):
         if devid:
             dev.setprop('id', devid)
         bridge = sxp.child_value(val, "bridge")
-        dev.bridge_add(bridge)
+        dev.up(bridge)
         vm.add_device('vif', dev)
         print 'vm_dev_vif> created', dev
         return id
index 6535ad3f37fa97bda98f79b495ac1514253b0b7e..ac201dd10d7525a2091ace329c0e4b6e97b296c3 100644 (file)
@@ -32,7 +32,7 @@ from twisted.internet import reactor
 from xen.xend import XendRoot
 xroot = XendRoot.instance()
 
-from xen.xend import XendBridge
+from xen.xend import Vifctl
 
 from SrvRoot import SrvRoot
 
@@ -48,8 +48,7 @@ def create(port=None, interface=None, bridge=0):
     reactor.listenTCP(port, site, interface=interface)
 
 def init_bridge():
-    XendBridge.bridge_create()
-    XendBridge.reconfigure()
+    Vifctl.init()
 
 def main(port=None, interface=None):
     create(port, interface)
index 01391f7b5fdfb7451ec494700dbe90de13dfae57..2b01805be69abcea9c92eb4dca3461b5ac1fa96e 100755 (executable)
@@ -4,7 +4,7 @@ from twisted.internet import defer
 
 from xen.xend import sxp
 from xen.xend import PrettyPrint
-from xen.xend import XendBridge
+from xen.xend import Vifctl
 
 import channel
 import controller
@@ -115,10 +115,11 @@ class NetDev(controller.Dev):
         self.mac = mac
         self.evtchn = None
         self.bridge = None
+        self.ipaddr = []
 
     def sxpr(self):
         vif = str(self.vif)
-        mac = ':'.join(map(lambda x: "%x" % x, self.mac))
+        mac = self.get_mac()
         val = ['netdev', ['vif', vif], ['mac', mac]]
         if self.bridge:
             val.append(['bridge', self.bridge])
@@ -128,20 +129,31 @@ class NetDev(controller.Dev):
                         self.evtchn['port2']])
         return val
 
-    def bridge_add(self, bridge):
-        self.bridge = XendBridge.vif_bridge_add(self.controller.dom, self.vif, bridge)
+    def get_vifname(self):
+        return "vif%d.%d" % (self.controller.dom, self.vif)
 
-    def bridge_rem(self):
-        if not self.bridge: return
-        XendBridge.vif_bridge_rem(self.controller.dom, self.vif, self.bridge)
-        self.bridge = None
+    def get_mac(self):
+        return ':'.join(map(lambda x: "%x" % x, self.mac))
+
+    def vifctl_params(self):
+        return { 'mac'   : self.get_mac(),
+                 'bridge': self.bridge,
+                 'ipaddr': self.ipaddr }
+
+    def up(self, bridge=None, ipaddr=[]):
+        self.bridge = bridge
+        self.ipaddr = ipaddr
+        Vifctl.up(self.get_vifname(), **self.vifctl_params())
+
+    def down(self):
+        Vifctl.down(self.get_vifname(), **self.vifctl_params())
 
     def destroy(self):
         def cb_destroy(val):
             self.controller.send_be_destroy(self.vif)
         print 'NetDev>destroy>', 'vif=', self.vif
         PrettyPrint.prettyprint(self.sxpr())
-        self.bridge_rem()
+        self.down()
         d = self.controller.factory.addDeferred()
         d.addCallback(cb_destroy)
         self.controller.send_be_disconnect(self.vif)
diff --git a/tools/xen/vifctl b/tools/xen/vifctl
new file mode 100644 (file)
index 0000000..095dc98
--- /dev/null
@@ -0,0 +1,148 @@
+#!/usr/bin/python
+#  -*- mode: python; -*-
+#============================================================================
+# Xen vif control script.
+#
+# vifctl init [bridge=<bridge>] [interface=<interface>]
+#
+#    Called when xend starts up. Default behaviour is to create <bridge>
+#    and add <interface> to it, moving its IP address to <bridge> and adjusting routes.
+#
+# vifctl (up|down) vif=<vif> mac=<mac> [bridge=<bridge>] (ipaddr=<ipaddr>)*
+#
+#    Called when a vif is brought up or down. Default behaviour is to add
+#    the vif to <bridge> on up and remove it from the bridge on down.
+#    If ipaddr is specified, iptables rules for the ip addresses are
+#    added on up and removed on down. The bridge a vif is added to can
+#    be set in the vm config.
+#
+# The default bridge is nbe-br.
+# The default interface is eth0.
+#
+#============================================================================
+
+import sys
+import types
+
+from xen.util import Brctl
+
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
+
+class VifControl:
+
+    prefix = 'vifctl_'
+
+    DEFAULT_BRIDGE = 'nbe-br'
+    DEFAULT_INTERFACE = 'eth0'
+
+    def __init__(self):
+        self.name = 'vifctl'
+    
+    def main(self, args):
+        if len(args) < 2:
+            usage(args)
+        self.name = args[0]
+        cmd = self.prefix + args[1]
+        meth = getattr(self, cmd, self.unknown)
+        meth(args[1:])
+
+    def usage(self, args, out=sys.stderr):
+        print >>out, 'Missing command, try \n%s help' % self.name
+
+    def unknown(self, args, out=sys.stderr):
+        print >>out, 'Unknown command:', args[1]
+        self.help(out=out)
+        sys.exit(1)
+
+    def help(self, out=sys.stdout):
+        print >>out, 'Commands are:',
+        for x in vars(self):
+            if x.startswith(prefix):
+                cmd = x[len(prefix):]
+                print  >>out, cmd,
+        print >>out
+
+    def getparams(self, d, args, req=[]):
+        """Parse args of the form 'key=val'. Valid keys are the ones
+        in the dict 'd' passed in. If entries in 'd' have list values the
+        values of the keys are appended.
+
+        If 'req' is specified it is a list of required keys.
+        """
+        for x in args:
+            (k, v) = x.split('=')
+            k = k.strip()
+            v = v.strip()
+            if k not in d:
+                print >>sys.stderr, 'Invalid parameter: ', k
+                sys.exit(1)
+            vold = d[k]
+            if isinstance(vold , types.ListType):
+                d[k] = vold + v
+            else:
+                d[k] = v
+        for x in req:
+            if not d[x]:
+                print >>sys.stderr, 'Missing parameter:', x
+            sys.exit(1)
+        return d
+            
+    def vifctl_help(self, args):
+        self.help()
+
+    def default_bridge(self):
+        return xroot.get_config_value('bridge', self.DEFAULT_BRIDGE)
+
+    def default_interface(self):
+        return xroot.get_config_value('interface', self.DEFAULT_INTERFACE)
+    
+    def vifctl_init(self, args):
+        """Entry point for 'vifctl init'.
+        """
+        d = { 'bridge'   : self.default_bridge(),
+              'interface': self.default_interface() }
+        params = self.getparams(d, args[1:])
+        interface = params['interface']
+        bridge = params['bridge']
+        # Create bridge 'bridge'.
+        Brctl.bridge_create(bridge)
+        # Reconfigure so that 'interface' is added to 'bridge',
+        # and 'bridge' has the IP address from 'interface'.
+        Brctl.reconfigure(interface, bridge)
+        
+    def vifparams(self, args):
+        d = { 'vif'   : None,
+              'mac'   : None,
+              'bridge': self.default_bridge(),
+              'ipaddr': [] }
+        d = self.getparams(d, args, req=['vif', 'mac'])
+        return d
+
+    def vifctl_up(self, args):
+        """Entry point for 'vifctl up'.
+        """
+        params = self.vifparams(args[1:])
+        # Add the vif to its bridge.
+        Brctl.vif_bridge_add(params)
+        if params['ipaddr']:
+            # Add iptables rules for the ip addresses.
+            vif = params['vif']
+            for ipaddr in params['ipaddr']:
+               Brctl.vif_restrict_addr(vif, ipaddr)
+
+    def vifctl_down(self, args):
+        """Entry point for 'vifctl down'.
+        """
+        params = self.vifparams(args[1:])
+        # Remove the vif from its bridge.
+        Brctl.vif_bridge_rem(params)
+        if params['ip']:
+            # Remove iptables rules for the ip addresses.
+            vif = params['vif']
+            for ip in params['ip']:
+               Brctl.vif_restrict_addr(vif, ip, delete=1)
+
+
+if __name__ == "__main__":
+    VifControl().main(sys.argv)